/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "vector.h"

namespace tri
{


TVector::TVector() : TObject(){
    this->x = 0;
    this->y = 0;
    this->z = 0;
}
TVector::TVector(float x,float y,float z) : TObject(){
    this->x = x;
    this->y = y;
    this->z = z;
}

TVector::TVector(float* v) : TObject(){
	this->x = v[0];
    this->y = v[1];
    this->z = v[2];
}

TVector::~TVector(){}

float TVector::length(){
	return sqrt((x * x) + (y * y) + (z * z));
}

tri::TVector TVector::crossProduct(tri::TVector* v){
	return tri::TVector(y*v->z - z*v->y, z*v->x - x*v->z , x*v->y - y*v->x);
}

float TVector::dotProduct(tri::TVector* v){
	return (x * v->x) + (y * v->y) + (z * v->z);
}

void TVector::normalize(){
	float len = length();
	x = x/len;
	y = y/len;
	z = z/len;
	
	x = utils::ABS(x)<0.0001 ? 0 : x;
	y = utils::ABS(y)<0.0001 ? 0 : y;
	z = utils::ABS(z)<0.0001 ? 0 : z;
}

tri::TVector& TVector::operator+=(const tri::TVector &v){
	x+=v.x;
	y+=v.y;
	z+=v.z;
	return *this;
}

tri::TVector& TVector::operator-=(const tri::TVector &v){
	x-=v.x;
	y-=v.y;
	z-=v.z;
	return *this;
}

tri::TVector TVector::operator-(const tri::TVector &v){
	return tri::TVector(x-v.x,y-v.y,z-v.z);
}

bool TVector::operator==(const tri::TVector &v){
	return x==v.x && y==v.y && z==v.z;
}

tri::TVector TVector::operator/(const float &v){
	return tri::TVector(x/v,y/v,z/v);
}

tri::TVector TVector::operator+(const tri::TVector &v){
	return tri::TVector(x+v.x,y+v.y,z+v.z);
}

tri::TVector& TVector::operator*=(const float &v){
	x*=v;
	y*=v;
	z*=v;
	return *this;
}

tri::TVector TVector::operator*(const float &v){
	return tri::TVector(x*v,y*v,z*v);
}

tri::TVector& TVector::operator/=(const float &v){
	x/=v;
	y/=v;
	z/=v;
	return *this;
}


float &TVector::operator[]( int index ){
	if(index==0){
		return x;
	}
	
	if(index==1){
		return y;
	}
	
	if(index==2){
		return z;
	}
	return x;
}

void TVector::rotateX(float angle){
	float theta = utils::degToRad(angle); 
	float _y = y*cos(theta) + z*sin(theta);
	float _z = -y*sin(theta) + z*cos(theta);
	y = _y;
	z = _z;
}

void TVector::rotateY(float angle){
	float theta = utils::degToRad(angle); 
	float _x = x*cos(theta) - z*sin(theta);
	float _z = z*cos(theta) + x*sin(theta);
	x = _x;
	z = _z;
}

void TVector::rotateZ(float angle){
	float theta = utils::degToRad(angle); 
	float _x = x*cos(theta) - y*sin(theta);
	float _z = y*cos(theta) + x*sin(theta);
	x = _x;
	z = _z;
}

std::string TVector::toString() const{
	std::string out;
	out += "TVector ";
	out += tri::utils::float2String(x) + " ";
	out += tri::utils::float2String(y) + " ";
	out += tri::utils::float2String(z) + " ";
	return out;
}


std::ostream& operator<<( std::ostream& out, const tri::TVector& v){
	out<<v.toString();
	return out;
}

}


